﻿@model WebExtras.JQDataTables.Datatable

<p>
  Sorting support can be added by slightly modifying the column definitions and using the <strong>Sort</strong> extension method.
</p>
<div class="well ui-well">
  <h4>Updating the column definitions to enable sorting</h4>
  Column definitions are created by instantiating the <i>WebExtras.JQDataTables.AOColumn</i> class. In order to enable sorting
  on a column, you MUST set the Sortable property to <strong>true</strong>. By default this will be set to <strong>false</strong> by
  the constructor.
  <pre><code>
  AOColumn dtColumn = new AOColumn
  {
    sTitle = "First Column",    <span class="comment">// Only the sTitle property is compulsory. All other properties are optional</span>
    <span class="highlight">bSortable = true,</span>
    sClass = "",                <span class="comment">// any extra CSS class you would like to apply to this column</span>
    sWidth = "10%",             <span class="comment">// specified as a CSS width</span>
    bVisible = true
  };  
  </code></pre>
</div>

<div class="well ui-well">
  <h4>Creating table settings</h4>
  Table settings are created by instantiating the <i>WebExtras.JQDataTables.DatatableSettings</i> class 
  <pre><code>  
  <span class="comment">// We need a collection of columns to be specified in the settings, so create an array from our column</span>
  AOColumn[] dtColumns = new AOColumn[] { dtColumn };

  DatatableSettings dtSettings = new DatatableSettings 
  (
    5,                                      <span class="comment">// specify the number of records per page</span>
    dtColumns,
    new AASort(0, ESort.Ascending),         <span class="comment">// specify one initial sort, multiple initial sorts, or leave null for no sort</span>
    <span class="highlight">"~/getsorteddata"</span>,                     <span class="comment">// specify an AJAX source to retrieve data from</span>
    "paged and sorted records",             <span class="comment">// specify a table footer suffix</span>
    "150px"                                 <span class="comment">// specify a maximum table height, once reached you will get scroll bars</span>
  );
  </code></pre>
</div>

<div class="well ui-well">
  <h4>Creating a data handler</h4>
  We make use of the C# LinqToSQL feature in order to simulate the sorting behavior. WebExtras provides an extension method for the 
  <strong>IEnumerable&lt;IEnumerable&lt;string&gt;&gt;</strong> interface which takes care of the sorting for us. 
  <pre><code>  
  public DatatableRecords GetSortedRecords(DatatableFilters filters)
  {
    <span class="comment">// Let's create the actual data to go into the table by adding 15 records</span>
    List&lt;string[]&gt; dtData = new List&lt;string[]&gt;();   <span class="comment">// Note that this still implements IEnumerable&lt;IEnumerable&lt;string&gt;&gt;</span>

    <span class="comment">// You can retrieve data from your repository here</span>
    for (int i = 0; i < 15; i++)
    {
      dtData.Add(new string[] { 
        string.Format("first column paged row {0}", i + 1), 
        string.Format("second column paged row {0}", i + 1) 
      });
    }

    DatatableRecords dtRecords = new DatatableRecords
    {
      sEcho = filters.sEcho,
      iTotalRecords = dtData.Length,                                        <span class="comment">// Total records in table</span>
      iTotalDisplayRecords = dtData.Length,                                 <span class="comment">// Total records to be displayed in the table</span>
      aaData = dtData<span class="highlight">.Sort(filters.iSortCol_0, filters.SortDirection)</span>        <span class="comment">// The sorted data to be displayed</span>
    };

    return dtRecords;
  }
  </code></pre>
</div>

<div class="well ui-well">
  <h4>Make the first page of the table</h4>
  We need to create the first page of the table in order to have the paging behavior kick in. This should be done when you display
  the table the first time.
  <pre><code>  
  DatatableRecords dtRecords = GetSortedRecords(new DatatableFilters { iDisplayStart = 0, iDisplayLength = 5 });
  Datatable dTable = new Datatable("sorted-table", dtSettings, dtRecords);
  </code></pre>
</div>

<div class="well ui-well">
  <h4>A slightly modified AJAX callback handler</h4>
  We will now make use of the method that we have already created before to do our grunt work and get the data. The fact that
  we have used DatatableFilters as one of the parameters means that we can simply forward the filtering parameters we got 
  from the HTTP GET request from the client side.
  <pre><code>
  public JsonResult GetSortedData(DatatableFilters filters)
  {
    DatatableRecords dtRecords = GetSortedRecords(filters);

    return Json(dtRecords, JsonRequestBehavior.AllowGet);
  }
  </code></pre>
</div>

<div class="well ui-well">
  <h4>And our sorting enabled output is</h4>
  <div class="output">
    @Html.Partial(MVC.Shared.Views.DatatablePartial, Model)
  </div>
</div>

<div class="well ui-well">
  <h4>Some details about the sorter extension</h4>
  <div class="content">
    <p>The sorter extension can currently handle columns with the following .NET base types and some special formats as listed below:</p>
    <ul>
      <li>string</li>
      <li>DateTime</li>
      <li>int, float, double, decimal</li>
      <li>currency i.e. data in the format: &euro;5.00, $6.00, &pound;7.00, &yen;8.00, &#8377;9.00. The sorter will strip the currencies and sort on the decimal number.
      It isn't intelligent enough to look up the current exchange rate and sort them, so beware!!
      <br />
        <strong>Rupees, Euro, Dollar, Pound and Yen</strong> are the currently supported
      currencies.
      </li>
      <li>HTML fields i.e data in format: &lt;a href='/somelink.html'&gt;some text&lt;/a&gt;. The sorter will strip the HTML tags and sort on the inner text of the tag.
      In this case the sorter will sort on <strong>some text</strong> and not the HTML A tag.</li>
    </ul>
  </div>
</div>

<div class="well ui-well">
  <h4>But my data doesn't fit any of the default formats :(</h4>
  <p>
    All defaults sorters have a fixed way in which they try to parse data and then apply the sorting logic on it. 
    However, you are not limited to only the default sorters.
    If you have a custom data format you are using, you can provide custom parsers to use in order to perform sorts.
  </p>
  <pre><code>
  <span class="comment">// An example custom parser to sort on the second character of the column data</span>
  Func&lt;string, object&gt; secondCharParser = (string str) => 
  {
    char[] arr = str.ToCharArray();
    
    if(arr.Length > 1)
      return arr[1];
    
    return null; 
  }

  <span class="comment">// Let's say we want to apply this custom parser to the second column of the table above</span>
  Dictionary&lt;int, Func&lt;string, object&gt;&gt; parsers = new Dictionary&lt;int, Func&lt;string, object&gt;&gt;();
  parsers.Add(<span class="highlight">1</span>, secondCharParser);           <span class="comment">// Note that the dictionary <span class="highlight">key</span> must match the column index in the table</span>
      
  <span class="comment">// This is how your DatatableRecords object creation would look</span>
  DatatableRecords dtRecords = new DatatableRecords
  {
    sEcho = filters.sEcho,
    iTotalRecords = dtData.Length,                                        
    iTotalDisplayRecords = dtData.Length,                                 
    aaData = dtData<span class="highlight">.Sort(filters.iSortCol_0, filters.SortDirection, parsers)</span>        <span class="comment">// Sorting with custom parser</span>
  };
  </code></pre>
</div>
